package com.tsd.core.config;

import com.alibaba.druid.filter.logging.Log4jFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.tsd.core.datasource.DataSourceProperties;
import com.tsd.core.datasource.DynamicDataSource;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;

/**
 * @Description:
 * @Author Hillpool
 * @Date 2019/3/11 16:50
 * @Modefied By:
 */
@Configuration
@PropertySource(value = {"classpath:application.properties"}, ignoreResourceNotFound = true)
@ComponentScan(basePackages = "com.tsd",
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceConfig {

    private final DataSourceProperties dataSourceProperties;

    public DataSourceConfig(DataSourceProperties properties) {
        this.dataSourceProperties = properties;
    }

    public DataSourceProperties getDataSourceProperties() {
        return dataSourceProperties;
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public DruidDataSource masterDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        //基本属性 url username password driverClassName
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        dataSource.setUrl(dataSourceProperties.getUrl());
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        //配置初始化大小、最小、最多连接数
        dataSource.setInitialSize(1);
        dataSource.setMaxActive(500);
        dataSource.setMinIdle(5);
        //配置获取连接等待超时时间
        dataSource.setMaxWait(60000);
        //MySQL的链接wait_time时长（300秒），超过时会自动关闭此连接
        //配置间隔多久进行一次检测，检测需要关闭的空闲连接，单位是毫秒
        dataSource.setTimeBetweenEvictionRunsMillis(60000);
        //配置一个连接在连接池中，最小生存的时间，单位是毫秒
        dataSource.setMinEvictableIdleTimeMillis(60000);
        //链接使用超过时间限制是否回收
        dataSource.setRemoveAbandoned(false);
        //超过时间限制时间（单位秒），目前为10分钟，如果有业务处理时间超过10分钟，可以适当调整。
        dataSource.setRemoveAbandonedTimeout(600);
        //链接回收的时候控制台打印信息，测试环境可以加上true，线上环境false。会影响性能。
        dataSource.setLogDifferentThread(true);
        //验证连接有效与否的SQL，不同的数据配置不同
        dataSource.setValidationQuery("SELECT 1 ");
        //此项配置为true即可，不影响性能，并且保证安全性。意义为：申请连接的时候检测，如果空闲时间大于timeBetweenEvictionRunsMillis，执行validationQuery检测连接是否有效
        dataSource.setTestWhileIdle(true);
        //这里建议配置为TRUE，防止取到的连接不可用。获取链接的时候，不校验是否可用，开启会有损性能
        dataSource.setTestOnBorrow(true);
        //归还链接到连接池的时候校验链接是否可用
        dataSource.setTestOnReturn(false);
        //打开PSCache，并且指定每个连接上的PSCache的大小
        dataSource.setPoolPreparedStatements(false);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
        return dataSource;
    }

    //切换数据源配置
    @Bean
    public DynamicDataSource multipleDataSource() {
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setMasterDataSource(this.masterDataSource());
        return dataSource;
    }

    //慢SQL记录
    @Bean
    public StatFilter statFilter() {
        StatFilter filter = new StatFilter();
        //慢sql时间设置,即执行时间大于200毫秒的都是慢sql
        filter.setSlowSqlMillis(200);
        filter.setLogSlowSql(true);
        return filter;
    }

    @Bean
    public Log4jFilter log4jFilter() {
        Log4jFilter filter = new Log4jFilter();
        filter.setDataSourceLogEnabled(true);
        filter.setStatementExecutableSqlLogEnable(true);
        return filter;
    }
}
